#include<bits/stdc++.h> 
using namespace std;
//	长途电话公司按照以下规则向顾客收费：打一通长途电话花费按照每分钟计费，单价
//	取决于那一天电话拨出去的时间。当一个顾客开始打长途，时间就会开始记录，所以
//	这个时间就是顾客拿起电话的时间。每个月，一封账单会送到客户家中，记录了每次
//	拨打的时长，我们需要准备每个月的账单，给出一系列拨号记录。
//1.每个输入包括一个测试用例，每个测试用例由两部分组成：单价结构以及通话记录
//2.单价结构由一行24个非负整数组成，单位是cents/minute，分别表示0点到1点，1点到
//	2点，以此类推的单价。
//3.下一行包含了一个正整数N≤1000，然后跟着N行通话记录。每条通话记录包括一个顾
//	客的姓名(由20个无空格字符组成的字符串)，一个时间和日期(MM:dd:HH:mm)，以及
//	一个单词on-line或者off-line。
//4.对于每一个测试用例，所有日期都在一个月份里面。每一个on-line记录都会按照时间
//	次序在后面提供一条同用户的off-line记录。每一条找不到匹配的记录都会被忽略。
//	确保整个记录中至少有一对记录是完好配对的，且假设没有两条记录是同一个用户同
//	一个时间的，时间用24小时制表示。
//5.对于每一个测试用例，需要输出每一个顾客的账单。账单必须以顾客名字的字母序排
//	序输出，对于每一个顾客，首先在一行中输出他的姓名以及月份。然后每一个有效通
//	话输出开始时间、结束时间、花费时长以及价格，时间格式为dd:HH:mm，时长单位为
//	分。这里的通话记录也要按照时间次序输出。最后输出这一整个月总花费。
//6.struct，stack实现配对，vector，map，set以及结构体运算符重载 
struct Record{	//通话记录的结构体，包括记录来源，记录时间以及类型 
	string name;
	string time;
	string type;
	Record(string v1, string v2, string v3){
		name = v1;
		time = v2;
		type = v3;
	}
	bool operator < (const Record &b) const{	//为了在set里存储后能直接按照姓名字典序和时间早晚排序，所以重载运算符 
		if(name<b.name) return name<b.name;
		else if(name==b.name) return time<b.time;
		else return false;
	}
}; 
struct Customer{	//顾客结构体，包括姓名，有效通话记录以及一个用来配对的通话记录的栈 
	string name;
	vector<string> records;
	stack<Record> remain;
	
	//为了简化代码书写，所以自己封装了向量和栈需要用到的函数 
	void push(string rec){
		records.push_back(rec);
	}
	Record top(){
		return remain.top();
	}
	void pop(){
		remain.pop();
	}
	void push(Record rec){
		stack<Record>().swap(remain);	//假设t1<t2<t3<t4，如果t1和t2是online，t3和t4是offline，则成功的只有t2和t3这一组，如果不能保证栈中只有0或1个online的话，会把t1与t4也配对，显然不能在t1~t4的时间段内再打t2~t3
		remain.push(rec);
	}
	bool empty(){
		return remain.empty();
	}
}; 
int rate[24];	//存储24个小时的价格 
int getMinute(string s){	//通过输入的日期，转换成分为单位的时间，以00:00:00为起点计算 
	int d, h, m = 0;
	d = stoi(s.substr(0,2));	//c++11支持stoi函数进行字符串向数字的转换 
	h = stoi(s.substr(3,2));
	m = stoi(s.substr(6,2));
	int second = m + h * 60 + d * 1440;
	return second; 
}
float getSum(string start, int minute){	//用于获得某条账单的消费，通过起始时间和总时长来计算 
	int start_hour, start_min;	//保存起始的时和分 
	float sum_=0;
	start_hour = stoi(start.substr(3,2));	
	start_min = stoi(start.substr(6,2));
	if(minute<(60-start_min)){	//如果起始时间到终止时间没有跨越某个小时的分界线，就直接这么算 
		return (rate[start_hour] * minute) / 100.00;
	}
	else{	//否则，先把起始时间这一端填满到下一个小时 
		sum_ += (60-start_min)*rate[start_hour];
		minute -= (60-start_min);
		start_hour = (start_hour + 1) % 24;	//注意如果跨日子了就会循环 
		while(minute>=60){	//然后当时间能包含1个小时的，就满满计算1个小时的费用 
			sum_ += 60 * rate[start_hour];
			minute -= 60;
			start_hour = (start_hour+1)%24;
		}	//直到最后剩下的不足一小时的时间就是结束时间超出某个小时分界线的时间，在把这个多出来的时间乘以单价即可 
		sum_ += minute*rate[start_hour];
		return (sum_) / 100.00; 	//单位是美元，需要/100.0 
	}
}
float make(string s){	//用于返回单条记录的消费，以及输出这条记录的信息 
	string starts = s.substr(3,8);
	string ends = s.substr(15,8);
	int start_time = getMinute(starts);	//计算起始时间 
	int end_time = getMinute(ends); 	//计算终止时间 
	int cha = end_time - start_time;	//求差得到通话时长 
	float sum_ = getSum(starts, cha);	//根据开始时间和时长来求得费用 
	cout<<starts<<" "<<ends<<" ";	//按照格式输出 
	cout<<cha<<" ";
	printf("$%.2f\n", sum_);
	return sum_;	//返回该记录的费用 
}
int main(){
	for(int i = 0;i<24;i++){
		cin>>rate[i];
	}
	int N;
	cin>>N;
	set<string> names;	//存名字用的set，用于判断一个人是否有被记录 
	map<string, Customer> custs;	//建立姓名查找顾客的映射 
	set<Record> all_records;	//存储通话记录的set，根据Record里重载的运算符来实现题目要求的排序 
	string month = "";	//保存这个月的月份信息 
	for(int i = 0;i<N;i++){
		string name, time, type;
		cin>>name>>time>>type;
		Record rec = Record(name, time, type); 	//生成记录 
		if(month=="") month = time.substr(0,2);	//为月份赋值，一次就好 
		all_records.insert(rec);	//插入记录总览中 
	}
	set<Record>::iterator it;	//准备遍历记录总览 
	for(it=all_records.begin();it!=all_records.end();it++){
		string name = (*it).name;
		string time = (*it).time;
		string type = (*it).type;
		if(names.find(name)!=names.end()){	//如果一个人已经有记录了，则做这些 
			Customer cust = custs[name];	//读取该名字代表的对象 
			if(type=="on-line"){	//如果又是一条on-line，则重新push这条记录进stack 
				Record r = Record(name, time, type);
				cust.push(r);
			}
			else{	//否则，读入的是off-line，可以开始匹配 
				if(!cust.empty()){	//如果栈是空的，就证明目前没有能够匹配的；不是空的。就说明能够匹配 
					Record onLine = cust.top();	//得到栈中唯一的栈顶 
					string rec = onLine.time + " " + time;	//生成时间对 
					cust.pop();	//弹出栈内元素 
					cust.push(rec);	//向顾客的vector中插入这条有效记录 
				}
			}
			custs[name] = cust;	//这里很关键，一定要更新一下映射，否则上面的Push操作都白做 
		}
		else{	//否则，表示目前还没有可以用于匹配的内容 
			if(type=="off-line") continue;	//如果这条记录的状态是off-line，则表示前面一直没有读到on_line,然后这条也不是，则直接跳过 
			names.insert(name);	//否则，表示这条是第一条on-line的，把这个人的名字插入 
			Customer cust = Customer();	//生成顾客对象 
			cust.name = name;	//赋值 
			Record r = Record(name, time, type);	//生成记录 
			cust.push(r);	//向该顾客的stack中插入记录 
			custs[name] = cust;	//建立映射表 
		}
	}
	map<string, Customer>::iterator iter;	//准备遍历映射表 
	for(iter=custs.begin();iter!=custs.end();iter++){
		string name = iter->first;	//键：姓名 
		Customer cust= iter->second;	//值：顾客 
		if(cust.records.size()==0) continue;	//如果顾客的记录向量是空的，则不输出 
		cout<<name<<" "<<month<<endl;	//否则先输出人名和月份 
		float sum_ = 0;	
		for(vector<string>::size_type i = 0;i<cust.records.size();i++){	//然后开始遍历记录向量 
			string rec = cust.records[i];	//拿到有效记录 
			sum_ += make(rec);	//通过make函数输出记录，获得这条记录的消费，然后累加 
		}
		printf("Total amount: $%.2f\n", sum_);	//输出总消费 
	}
	return 0;
}